package file_utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import utils.ArgumentAssertion;

public class FileUtils {

	public static final long KILO = 1024;

	public static final long MEGA = KILO * 1024;

	public static final long GIGA = MEGA * 1024;

	private static final Random RANDOM = new Random();

	public static File divideIntoSortedChunks(File file,
	        long maxChuckSizeInBytes) throws IOException {

		ArgumentAssertion.assertNotNull("file", file);
		ArgumentAssertion.assertPositive("maxChuckSizeInBytes",
		        maxChuckSizeInBytes);

		BufferedReader reader = new BufferedReader(new FileReader(file));

		File chunksFolder = createTempFolder();

		File chunk = File.createTempFile("chunk", "", chunksFolder);
		long currentChunkSizeInBytes = 0;
		String line;
		List<String> lines = new LinkedList<String>();
		while ((line = reader.readLine()) != null) {
			currentChunkSizeInBytes += line.length() + 1;

			if (currentChunkSizeInBytes > maxChuckSizeInBytes) {
				currentChunkSizeInBytes = line.length() + 1;
				Collections.sort(lines);
				flush(chunk, lines);
				lines = new LinkedList<String>();
				chunk = File.createTempFile("chunk", "", chunksFolder);
			}

			lines.add(line);
		}

		Collections.sort(lines);
		flush(chunk, lines);

		return chunksFolder;
	}

	private static void flush(File file, List<String> lines) throws IOException {
		BufferedWriter writer = new BufferedWriter(new FileWriter(file));

		for (String line : lines) {
			writer.write(line);
			writer.newLine();
		}

		writer.close();
	}

	private static File createTempFolder() throws IOException {
		String folderPrefix = "chunks";
		while (true) {
			String folderSuffix = Integer.toString(Math.abs(RANDOM.nextInt()));
			File tempFolder = new File(folderPrefix + folderSuffix);
			if (!tempFolder.exists()) {
				tempFolder.mkdir();
				return tempFolder;
			}
		}
	}
}
